package com.hmjk.health.background.data;

import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.text.format.Time;
import android.util.Log;

import com.hmjk.health.HealthApp;
import com.hmjk.health.background.DataManager;
import com.hmjk.health.background.DatabaseHelper;
import com.hmjk.health.background.NetService;

public class DeviceSubInfoUpdate extends DataUpdated{
	private static String TAG = DeviceSubInfoUpdate.class.getSimpleName();
	private ArrayList<SUBACCOUNT> mSubAccountList = new ArrayList<SUBACCOUNT>();
	private int index = 0;
	private boolean working = false;
	private boolean doSingle = false;
	
	private void logd(String info){
		Log.d(TAG, info);
	}

	class SUBACCOUNT{
		String tid;
		String subcode;
		String table;
		long reqtime;
	}
	
	public DeviceSubInfoUpdate(HealthApp app, DataManager dm, DataUpdated base) {
		super(app, dm, base);
		UPDATE_TIME = 60 * 60 * 1000;
		mBaseData.setNotifer(DataManager.F_DEVICESUBINFO, this);
	}

	@Override
	public void setUserData(Object data) {
		logd("setUserData");
		reqTime = 0;
		upTime = 0;
	}

	@Override
	public long delay() {
		long curMs = System.currentTimeMillis();
		long del = curMs - upTime;
		logd("delay curMs="+curMs+" upTime="+upTime+" del="+del);
		if(del >= UPDATE_TIME){
			logd("delay 0");
			return 0;
		}else{
			logd("delay (UPDATE_TIME - del) = "+(UPDATE_TIME - del));
			return (UPDATE_TIME - del);
		}
	}
	
	private void getSubAccount(){
		DatabaseHelper dh = mDm.getDatabaseHelper();
		if(dh == null)
			return;
		
		JSONObject json = (JSONObject) mBaseData.check(null);
		
		mSubAccountList.clear();
		index = 0;
		if(json != null){
			try {
				JSONArray ar = json.getJSONArray("array");
				int len = ar.length();
				for(int i = 0; i < len; i++){
					JSONObject e = ar.getJSONObject(i);
					String tid = e.getString("tid");
					String table = e.getString("table");
					if(table.trim().isEmpty())
						continue;
					
					Cursor c = dh.getItemsInTable(table);
					if(c.getCount() > 0){
						while(c.moveToNext()){
							String subcode = c.getString(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_CODE));
							
							if((subcode != null) && (subcode.trim().length() > 0)){
								SUBACCOUNT ob = new SUBACCOUNT();
								ob.tid = tid;
								ob.table = table;
								ob.subcode = subcode;
								mSubAccountList.add(ob);
							}
						}
					}
				}
			} catch (JSONException e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
	}
	
	private void doNextRequest(){
		logd("doNextRequest");
		if(doSingle){
			doSingle = false;
			working = false;
			return;
		}
		
		int size = mSubAccountList.size();
		if(size > 0){
			index ++;
			if(index < size){
				doRequest();
			}else {
				working = false;
			}
		}else {
			working = false;
		}
	}
	
	private void doRequest(){
		if(mSubAccountList.size() == 0){
			logd("doRequest mSubAccountList is empty");
			working = false;
			return;
		}
		logd("doRequest");
		
		SUBACCOUNT data = mSubAccountList.get(index);
		Intent si = new Intent(NetService.GET_DATA_ACTION);
		si.putExtra("sub_act", NetService.GET_DEVICE_SUB_INFO);
		si.putExtra("tid", data.tid);
		si.putExtra("subcode", data.subcode);
		si.putExtra("table", data.table);
		logd("doRequest: index = "+index+";tid="+data.tid+";subcode="+data.subcode);
		Time t = new Time();
		t.setToNow();
		String stamp = "GET_DEVICE_SUB_INFO" + t.toString(); 
		si.putExtra("stamp",stamp);
		mApp.addNetHandler(stamp,mDm.getBackGroundHandler());
		mApp.startService(si);
		data.reqtime = System.currentTimeMillis();
	}
	
	private void doSingleRequest(SUBACCOUNT data){
		doSingle = true;
		
		Intent si = new Intent(NetService.GET_DATA_ACTION);
		si.putExtra("sub_act", NetService.GET_DEVICE_SUB_INFO);
		si.putExtra("tid", data.tid);
		si.putExtra("subcode", data.subcode);
		si.putExtra("table", data.table);
		
		Time t = new Time();
		t.setToNow();
		String stamp = "GET_DEVICE_SUB_INFO" + t.toString(); 
		si.putExtra("stamp",stamp);
		mApp.addNetHandler(stamp,mDm.getBackGroundHandler());
		mApp.startService(si);
		data.reqtime = System.currentTimeMillis();
	}
	
	@Override
	public boolean grab() {
		if(working){
			logd("grab working now");
			return false;
		}
		
		getSubAccount();
		
		if(mSubAccountList.size() == 0){
			logd("grab mSubAccountList is empty");
			return false;
		}
		
		long curMs = System.currentTimeMillis();
		logd("grab curMs="+curMs+" reqTime="+reqTime);
		if((curMs - reqTime) > UPDATE_TIME){
			working = true;
			doRequest();
			reqTime = curMs;
			logd("grab req sent!");
			return true;
		}
		
		return false;
	}

	@Override
	public boolean grabByUser() {
		if(working){
			logd("grabByUser working now");
			return false;
		}
		
		getSubAccount();
		if(mSubAccountList.size() == 0){
			logd("grabByUser mSubAccountList is empty");
			return false;
		}
		
		long curMs = System.currentTimeMillis();
		logd("grabByUser curMs="+curMs+" reqTime="+reqTime);
		if((curMs - reqTime) > MIN_QUERY_DUR * 1000){
			working = true;
			doRequest();
			reqTime = curMs;
			logd("grabByUser req sent!");
			return true;
		}
		
		return false;
	}
	
	private SUBACCOUNT geSubAccountDataNode(String tid, String subcode){
		for(SUBACCOUNT d:mSubAccountList){
			if(d.tid.equals(tid) && d.subcode.equals(subcode)){
				return d;
			}
		}
		
		return null;
	}
	
	
	@Override
	public boolean grabByUserWithSingleArgs(Object args){
		if(args == null)
			return false;
		
		String[] argsArrays = (String[])args;
		if(argsArrays[0].isEmpty() || argsArrays[1].isEmpty()){
			return false;
		}
		
		if(working){
			logd("grabByUserWithSingleArgs working");
			return false;
		}
		
		String tid  = argsArrays[0];
		String subcode = argsArrays[1];
		SUBACCOUNT d = geSubAccountDataNode(tid, subcode);
		if(d == null){
			logd("grabByUserWithSingleArgs not exist:tid="+tid+" subcode = "+subcode);
			return false;
		}
		
		logd("grabByUserWithSingleArgs tid=" + tid + " subcode=" + subcode);
		
		long curMs = System.currentTimeMillis();
		logd("grabByUserWithSingleArgs curMs="+curMs+" reqTime="+reqTime);
		if((curMs - d.reqtime) > 10 * 1000){
			working = true;
			doSingleRequest(d);
			logd("grabByUserWithSingleArgs req sent!");
			return true;
		}
		
		return false;
	}

	@Override
	public void receive(String stamp, String sjson) {
		DatabaseHelper dh = mDm.getDatabaseHelper();
		if(dh == null)
			return;
		
		if(stamp.startsWith("GET_DEVICE_SUB_INFO")){
			if(sjson != null){
				boolean update = false;
				String tid = "";
				String subcode = "";
				try {
					JSONObject json = new JSONObject(sjson);
					int code = json.getInt("code");
					if(code == 200){
						String state = json.getString("state");
						if(state.equalsIgnoreCase("00")){
							JSONObject sd = json.getJSONObject("senddata");
							JSONObject recdata = json.getJSONObject("recdata");
							if(recdata != null){
								tid = sd.getString("tid");
								subcode = sd.getString("subcode");
								String table = sd.getString("table");
								if(dh.isTableExists(table)){
								upTime = System.currentTimeMillis();
								
								ContentValues cv = new ContentValues();
								cv.put(DatabaseHelper.DEVSUBINFO_TID, tid);
								cv.put(DatabaseHelper.DEVSUBINFO_CODE, subcode);
								
								String nick = "";
								if(recdata.has("nickname")){
									nick = recdata.getString("nickname");
								}
								cv.put(DatabaseHelper.DEVSUBINFO_NICK, nick);
								
								String birthday = "";
								if(recdata.has("birthday")){
									birthday = recdata.getString("birthday");
								}
								cv.put(DatabaseHelper.DEVSUBINFO_BIRTHDAY, birthday);
								
								String gender = "u";
								if(recdata.has("gender")){
									gender = recdata.getString("gender").trim();
									if(gender.equalsIgnoreCase("M")){
										gender = "m";
									}else if(gender.equalsIgnoreCase("F")){
										gender = "f";
									}else
										gender = "u";
								}
								
								cv.put(DatabaseHelper.DEVSUBINFO_GENDER, gender);
								
								double height = 0.0f;
								if(recdata.has("height")){
									String sh = recdata.getString("height");
									try{
									height = Double.parseDouble(sh);
									}catch(NumberFormatException e){
										height = 0.0f;
									}
								}
								cv.put(DatabaseHelper.DEVSUBINFO_HEIGHT, height);
								
								double weight = 0.0f;
								if(recdata.has("weight")){
									String sw = recdata.getString("weight");
									try{
										weight = Double.parseDouble(sw);
									}catch(NumberFormatException e){
										weight = 0.0f;
									}
								}
								cv.put(DatabaseHelper.DEVSUBINFO_WEIGHT, weight);
								cv.put(DatabaseHelper.DEVSUBINFO_TIME, upTime);
								
								dh.updateOneItemInDevsubinfoTable(table ,tid, subcode, cv);
									
								dh.closeDB();
								update = true;
								}else{
									dh.closeDB();
									update = false;
								}
							}
						}
					}
					
				} catch (JSONException e) {
					// TODO: handle exception
					e.printStackTrace();
				}
				logd("received:tid="+tid+",subcode="+subcode);
				doNextRequest();
				Intent i = new Intent(DataManager.DATA_UPDATE_ACTION);
				i.putExtra("type",DataManager.F_DEVICESUBINFO);
				i.putExtra("state", update);
				i.putExtra("tid", tid);
				i.putExtra("subcode", subcode);
				mApp.sendBroadcast(i);
			}
		}
	}

	@Override
	public Object check(String[] arg) {
		JSONObject ret = null;
		DatabaseHelper dh = mDm.getDatabaseHelper();
		if(dh == null)
			return null;
		
		if((arg == null) || (arg.length < 2)){
			return null;
		}
		
		String type = arg[0];
		if(type.equalsIgnoreCase("TID") || type.equalsIgnoreCase("TID_SUBCODE")){
			String tid = arg[1];
			String checkSub = null;
			if(type.equalsIgnoreCase("TID_SUBCODE")){
				checkSub = arg[2];
			}
			
			String [] checkarg = new String[1];
			checkarg[0] = tid;
			JSONObject o = (JSONObject) mBaseData.check(checkarg);
			if(o == null)
				return null;
			String table = null;
			Cursor c = null;
			try {
				table = o.getString("table");
				if((table != null) && (table.trim().length() > 0)){
					c = dh.getItemsInTable(table);
					ret = new JSONObject();
					if(c.getCount() > 0){
						JSONArray array = new JSONArray();
						long time = 0;
						while(c.moveToNext()){
							String subcode = c.getString(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_CODE));
							if(checkSub != null){
								if(checkSub.equals(subcode) == false){
									continue;
								}
							}
							String nick = c.getString(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_NICK));
							String birthday = c.getString(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_BIRTHDAY));
							String gender = c.getString(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_GENDER));
							double height = c.getDouble(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_HEIGHT));
							double weight = c.getDouble(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_WEIGHT));
							time = c.getLong(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_TIME));
							
							JSONObject e = new JSONObject();
							e.put("tid", tid);
							e.put("subcode", subcode);
							e.put("nickname", nick);
							e.put("birthday", birthday);
							e.put("gender", gender);
							e.put("height", height);
							e.put("weight", weight);
							array.put(e);
						}
						ret.put("array", array);
						ret.put("uptime", time);
					}else {
						JSONArray array = new JSONArray();
						ret.put("array", array);
						ret.put("uptime", upTime);
					}
					if(c != null)
						c.close();
				}
			} catch (JSONException e1) {
				e1.printStackTrace();
			}
			if(c != null)
				c.close();
			dh.closeDB();
		}else if(type.equalsIgnoreCase("FIRST")){
			JSONObject l = (JSONObject) mBaseData.check(null);
			if(l == null)
				return null;
			Cursor c = null;
			try {
				JSONArray arr = l.getJSONArray("array");
				int len = arr.length();
				
				for(int i=0; i< len;i++){
					JSONObject o = arr.getJSONObject(i);
					String table = o.getString("table");
					String tid = o.getString("tid");
					if((table != null) && (table.trim().length() > 0)){
						c = dh.getItemsInTable(table);
						if(c.getCount() > 0){
							ret = new JSONObject();
							JSONArray array = new JSONArray();
							long time = 0;
							while(c.moveToNext()){
								String subcode = c.getString(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_CODE));
								String nick = c.getString(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_NICK));
								String birthday = c.getString(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_BIRTHDAY));
								String gender = c.getString(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_GENDER));
								double height = c.getDouble(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_HEIGHT));
								double weight = c.getDouble(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_WEIGHT));
								time = c.getLong(c.getColumnIndex(DatabaseHelper.DEVSUBINFO_TIME));
								
								JSONObject e = new JSONObject();
								e.put("tid", tid);
								e.put("subcode", subcode);
								e.put("nickname", nick);
								e.put("birthday", birthday);
								e.put("gender", gender);
								e.put("height", height);
								e.put("weight", weight);
								array.put(e);
							}
							ret.put("array", array);
							ret.put("uptime", time);
							break;
						}
						if(c != null)
							c.close();
					}
				}
			} catch (JSONException e1) {
				e1.printStackTrace();
			}
			
			if(c != null)
				c.close();
			
			dh.closeDB();
		}
		return ret;
	}

	@Override
	public boolean commit(Object data) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void release() {
		// TODO Auto-generated method stub
		
	}

}
